package com.wcs.exam.controller.admin.biz;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.event.SyncReadListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.wcs.exam.common.base.BaseBiz;
import com.wcs.exam.common.base.Result;
import com.wcs.exam.common.base.exception.BaseException;
import com.wcs.exam.common.base.page.Page;
import com.wcs.exam.common.base.page.PageUtil;
import com.wcs.exam.common.constant.BaseConstant;
import com.wcs.exam.common.constant.RedisConstant;
import com.wcs.exam.common.enums.*;
import com.wcs.exam.common.excel.QuestionUploadExcel;
import com.wcs.exam.common.excel.QuestionUploadExcelParse;
import com.wcs.exam.common.llm.Llm;
import com.wcs.exam.common.llm.LlmService;
import com.wcs.exam.common.llm.bean.AiQuestion;
import com.wcs.exam.common.util.BeanUtil;
import com.wcs.exam.controller.admin.req.*;
import com.wcs.exam.controller.admin.resp.*;
import com.wcs.exam.controller.biz.CategoryCommonBiz;
import com.wcs.exam.controller.biz.QuestionCommonBiz;
import com.wcs.exam.controller.biz.SysConfigCommonBiz;
import com.wcs.exam.controller.biz.resp.QuestionDetailResp;
import com.wcs.exam.controller.biz.resp.QuestionTypeCountResp;
import com.wcs.exam.dao.*;
import com.wcs.exam.dao.impl.mapper.entity.*;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Admin-试题信息
 *
 * @author wcs
 * @since 2025-03-11
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AdminQuestionBiz extends BaseBiz {

    @NotNull
    private final RedissonClient redissonClient;
    @NotNull
    private final HttpServletResponse response;

    @NotNull
    private final LlmService llmService;

    @NotNull
    private final CategoryCommonBiz categoryCommonBiz;
    @NotNull
    private final QuestionCommonBiz questionCommonBiz;

    @NotNull
    private final QuestionDao dao;
    @NotNull
    private final QuestionOptionDao questionOptionDao;
    @NotNull
    private final PaperDao paperDao;
    @NotNull
    private final PaperQuestionDao paperQuestionDao;
    @NotNull
    private final CategoryDao categoryDao;
    private final SysConfigCommonBiz sysConfigCommonBiz;

    /**
     * 试题信息-分页
     *
     * @param req 试题信息-分页查询参数
     * @return 试题信息
     */
    public Result<Page<AdminQuestionPageResp>> page(AdminQuestionPageReq req) {
        // 处理查询参数
        Set<Long> categoryIds = new HashSet<>();
        if (ObjectUtil.isNotNull(req.getCategoryId())) {
            categoryIds.add(req.getCategoryId());
            if (ObjectUtil.isNull(req.getOnlyCurrentCategory()) || Boolean.FALSE.equals(req.getOnlyCurrentCategory())) {
                List<Long> categoryChildrenIds = categoryCommonBiz.listChildrenIdById(req.getCategoryId());
                if (CollectionUtil.isNotEmpty(categoryChildrenIds)) {
                    categoryIds.addAll(categoryChildrenIds);
                }
            }
        }
        LocalDateTime endGmtCreate = ObjectUtil.isNotNull(req.getEndGmtCreate()) ? req.getEndGmtCreate().plusSeconds(59) : null;

        // 处理查询条件
        LambdaQueryWrapper<Question> wrapper = new LambdaQueryWrapper<Question>()
                .in(CollectionUtil.isNotEmpty(categoryIds), Question::getCategoryId, categoryIds)
                .eq(ObjectUtil.isNotNull(req.getDifficultyLevel()), Question::getDifficultyLevel, req.getDifficultyLevel())
                .eq(ObjectUtil.isNotNull(req.getQuestionType()), Question::getQuestionType, req.getQuestionType())
                .like(StrUtil.isNotBlank(req.getQuestionTitle()), Question::getQuestionTitle, req.getQuestionTitle())
                .like(StrUtil.isNotBlank(req.getQuestionAnalysis()), Question::getQuestionAnalysis, req.getQuestionAnalysis())
                .eq(ObjectUtil.isNotNull(req.getStatus()), Question::getStatus, req.getStatus())
                .ge(ObjectUtil.isNotNull(req.getBeginGmtCreate()), Question::getGmtCreate, req.getBeginGmtCreate())
                .le(ObjectUtil.isNotNull(endGmtCreate), Question::getGmtCreate, endGmtCreate)
                .notIn(CollectionUtil.isNotEmpty(req.getExcludeIds()), Question::getId, req.getExcludeIds())
                // 排序
                .orderByDesc(Question::getSort)
                .orderByDesc(Question::getId);

        // 分页查询
        IPage<Question> page = dao.page(PageDTO.of(req.getPageCurrent(), req.getPageSize()), wrapper);
        Page<AdminQuestionPageResp> respPage = PageUtil.transform(page, AdminQuestionPageResp.class);
        if (ObjectUtil.isNull(respPage) || CollectionUtil.isEmpty(respPage.getList())) {
            return Result.success(respPage);
        }
        Set<Long> questionIds = respPage.getList().stream().map(AdminQuestionPageResp::getId).collect(Collectors.toSet());

        // 查询引用信息
        Map<Long, Boolean> citeMap = questionCommonBiz.getQuestionCiteStatus(questionIds);
        for (AdminQuestionPageResp resp : respPage.getList()) {
            resp.setCite(citeMap.getOrDefault(resp.getId(), Boolean.FALSE));
        }
        return Result.success(respPage);
    }

    /**
     * 试题信息-添加
     *
     * @param req 试题信息
     * @return 添加结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<String> save(AdminQuestionSaveReq req) {
        // 参数校验
        if (QuestionTypeEnum.isExistOption(req.getQuestionType())) {
            if (CollectionUtil.isEmpty(req.getOptions())) {
                return Result.error("试题选项不能为空");
            }
        }
        if (StrUtil.isBlank(req.getQuestionAnswer())) {
            return Result.error("试题答案不能为空");
        }

        RLock lock = redissonClient.getLock(RedisConstant.Exam.QUESTION);
        try {
            boolean lockRes = lock.tryLock(RedisConstant.DEFAULT_WAIT_TIME, RedisConstant.DEFAULT_LEASE_TIME, TimeUnit.SECONDS);
            if (!lockRes) {
                log.warn("试题添加锁超时");
                return Result.error(toI18nFail());
            }

            Question question = BeanUtil.copyProperties(req, Question.class);
            question.setId(IdWorker.getId());
            question.setQuestionAnalysis(StrUtil.isNotBlank(req.getQuestionAnalysis()) ? req.getQuestionAnalysis() : "");
            question.setSort(dao.getMaxSort() + 1);

            if (QuestionTypeEnum.isExistOption(req.getQuestionType())) {
                // 单选、多选、判断是存在选项的
                if (question.getQuestionType().equals(QuestionTypeEnum.JUDGMENT.getCode())) {
                    // 判断题单独添加选项
                    List<AdminQuestionSaveReq.Option> options = new ArrayList<>();
                    for (String answer : BaseConstant.ESTIMATE_ANSWER_LIST) {
                        AdminQuestionSaveReq.Option option = new AdminQuestionSaveReq.Option();
                        option.setOptionContent(answer);
                        options.add(option);
                    }
                    req.setOptions(options);
                }
                List<QuestionOption> saveOptions = getSaveQuestionOptions(question, req.getOptions());
                questionOptionDao.saveBatch(saveOptions);
            }
            dao.save(question);
            return Result.success(toI18nSuccess());
        } catch (InterruptedException e) {
            log.error("试题添加失败", e);
            Thread.currentThread().interrupt();
            throw new BaseException(toI18nFail());
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    /**
     * 获取保存的试题选项信息
     *
     * @param question 试题信息
     * @param options  选项信息
     * @return 待保存试题选项
     */
    private static List<QuestionOption> getSaveQuestionOptions(Question question, List<AdminQuestionSaveReq.Option> options) {
        List<QuestionOption> saveOptions = new ArrayList<>();
        int optionSort = 1;
        for (AdminQuestionSaveReq.Option option : options) {
            QuestionOption saveOption = getSaveOption(question.getId(), option.getOptionContent(), optionSort++);
            saveOptions.add(saveOption);
        }
        return saveOptions;
    }

    /**
     * 获取保存试题的选项信息
     *
     * @param questionId    试题信息
     * @param optionContent 选项内容
     * @param optionSort    选项排序
     * @return 待保存试题选项
     */
    private static QuestionOption getSaveOption(Long questionId, String optionContent, Integer optionSort) {
        QuestionOption saveOption = new QuestionOption();
        saveOption.setId(IdWorker.getId());
        saveOption.setQuestionId(questionId);
        saveOption.setOptionContent(optionContent);
        saveOption.setSort(optionSort);
        saveOption.setStatus(StatusEnum.NORMAL.getCode());
        return saveOption;
    }

    /**
     * 试题信息-批量添加
     *
     * @param reqs 试题信息-批量添加
     * @return 添加结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<String> batchSave(List<AdminQuestionSaveReq> reqs) {
        if (CollectionUtil.isEmpty(reqs)) {
            return Result.error("题目不能为空");
        }

        RLock lock = redissonClient.getLock(RedisConstant.Exam.QUESTION);
        try {
            boolean lockRes = lock.tryLock(RedisConstant.DEFAULT_WAIT_TIME, RedisConstant.DEFAULT_LEASE_TIME, TimeUnit.SECONDS);
            if (!lockRes) {
                log.warn("试题添加锁超时");
                return Result.error(toI18nFail());
            }

            Integer maxSort = dao.getMaxSort();

            List<Question> questionList = new ArrayList<>();
            List<QuestionOption> questionOptionList = new ArrayList<>();
            for (AdminQuestionSaveReq req : reqs) {
                // 参数校验
                if (QuestionTypeEnum.isExistOption(req.getQuestionType())) {
                    if (CollectionUtil.isEmpty(req.getOptions())) {
                        return Result.error("试题选项不能为空");
                    }
                }
                if (StrUtil.isBlank(req.getQuestionAnswer())) {
                    return Result.error("试题答案不能为空");
                }

                Question question = BeanUtil.copyProperties(req, Question.class);
                question.setId(IdWorker.getId());
                question.setQuestionAnalysis(StrUtil.isNotBlank(req.getQuestionAnalysis()) ? req.getQuestionAnalysis() : "");
                question.setSort(++maxSort);

                if (QuestionTypeEnum.isExistOption(req.getQuestionType())) {
                    // 单选、多选、判断是存在选项的
                    if (question.getQuestionType().equals(QuestionTypeEnum.JUDGMENT.getCode())) {
                        // 判断题单独添加选项
                        List<AdminQuestionSaveReq.Option> options = new ArrayList<>();
                        for (String answer : BaseConstant.ESTIMATE_ANSWER_LIST) {
                            AdminQuestionSaveReq.Option option = new AdminQuestionSaveReq.Option();
                            option.setOptionContent(answer);
                            options.add(option);
                        }
                        req.setOptions(options);
                    }

                    // 获取保存的试题选项信息
                    List<QuestionOption> saveOptions = getSaveQuestionOptions(question, req.getOptions());
                    if (CollectionUtil.isNotEmpty(saveOptions)) {
                        questionOptionList.addAll(saveOptions);
                    }
                }

                questionList.add(question);
            }

            if (CollectionUtil.isNotEmpty(questionList)) {
                dao.saveBatch(questionList);
            }
            if (CollectionUtil.isNotEmpty(questionOptionList)) {
                questionOptionDao.saveBatch(questionOptionList);
            }
        } catch (InterruptedException e) {
            log.error("试题添加失败", e);
            Thread.currentThread().interrupt();
            throw new BaseException(toI18nFail());
        } finally {
            // 释放锁
            lock.unlock();
        }
        return Result.success(toI18nSuccess());
    }

    /**
     * 试题信息-查看
     *
     * @param id 主键ID
     * @return 试题信息
     */
    public Result<AdminQuestionViewResp> view(Long id) {
        QuestionDetailResp question = questionCommonBiz.getDetailById(id);
        if (ObjectUtil.isNull(question)) {
            return Result.error("试题信息不存在");
        }
        return Result.success(BeanUtil.copyProperties(question, AdminQuestionViewResp.class));
    }

    /**
     * 试题信息-编辑
     *
     * @param req 试题信息-编辑对象
     * @return 编辑结果
     */
    public Result<String> edit(AdminQuestionEditReq req) {
        // 参数校验
        if (QuestionTypeEnum.isExistOption(req.getQuestionType())) {
            if (CollectionUtil.isEmpty(req.getOptions())) {
                return Result.error("试题选项不能为空");
            }
        }
        if (StrUtil.isBlank(req.getQuestionAnswer())) {
            return Result.error("试题答案不能为空");
        }

        // 获取校验试题信息
        Question question = dao.getById(req.getId());
        if (ObjectUtil.isNull(question)) {
            return Result.error("试题信息不存在");
        }

        // 更新试题信息
        Question updateQuestion = BeanUtil.copyProperties(req, Question.class);
        updateQuestion.setQuestionAnswer(StrUtil.isNotBlank(req.getQuestionAnswer()) ? req.getQuestionAnswer() : null);
        updateQuestion.setQuestionAnalysis(StrUtil.isNotBlank(req.getQuestionAnalysis()) ? req.getQuestionAnalysis() : null);
        updateQuestion.setGmtCreate(null);
        updateQuestion.setGmtModified(null);
        updateQuestion.setQuestionType(question.getQuestionType());

        // 处理题目更新
        if (QuestionTypeEnum.SINGLE_CHOICE.getCode().equals(updateQuestion.getQuestionType()) || QuestionTypeEnum.MULTIPLE_CHOICE.getCode().equals(updateQuestion.getQuestionType())) {
            // 单选和多选
            List<QuestionOption> questionOptions = questionOptionDao.listByQuestionId(updateQuestion.getId());
            Map<Long, QuestionOption> optionMap = new HashMap<>();
            if (CollectionUtil.isNotEmpty(questionOptions)) {
                questionOptions.forEach(item -> optionMap.put(item.getId(), item));
            }

            // 删除题目选项
            questionOptionDao.deleteByQuestionId(updateQuestion.getId());

            List<QuestionOption> saveOptions = new ArrayList<>();
            int optionSort = 1;
            for (AdminQuestionEditReq.Option option : req.getOptions()) {
                QuestionOption saveOption = getSaveOption(updateQuestion.getId(), option.getOptionContent(), optionSort++);
                // 判断是否存在ID，存在则更新，不存在则新增
                if (ObjectUtil.isNotNull(option.getId()) && optionMap.containsKey(option.getId())) {
                    saveOption.setId(option.getId());
                }
                saveOptions.add(saveOption);
            }

            if (CollectionUtil.isNotEmpty(saveOptions)) {
                questionOptionDao.saveBatch(saveOptions);
            }
        }

        dao.updateById(updateQuestion);
        return Result.success(toI18nSuccess());
    }

    /**
     * 试题信息-排序
     *
     * @param reqs 试题信息-排序对象
     * @return 排序结果
     */
    public Result<String> sort(List<AdminQuestionSortReq> reqs) {
        // 查询获取试题信息
        List<Question> questionList = dao.lambdaQuery()
                .in(Question::getId, reqs.stream().map(AdminQuestionSortReq::getId).collect(Collectors.toSet()))
                .list();
        if (CollectionUtil.isEmpty(questionList)) {
            return Result.success(toI18nSuccess());
        }

        RLock lock = redissonClient.getLock(RedisConstant.Exam.QUESTION);
        try {
            boolean lockRes = lock.tryLock(RedisConstant.DEFAULT_WAIT_TIME, RedisConstant.DEFAULT_LEASE_TIME, TimeUnit.SECONDS);
            if (!lockRes) {
                log.warn("试题排序获取锁超时");
                return Result.error(toI18nFail());
            }

            dao.lambdaUpdate()
                    .in(Question::getId, questionList.stream().map(Question::getId).collect(Collectors.toSet()))
                    .setDecrBy(Question::getSort, Integer.MAX_VALUE)
                    .update();

            // 处理待更新排序的试题信息
            Map<Long, Integer> sortMap = new HashMap<>();
            reqs.forEach(item -> sortMap.put(item.getId(), item.getSort()));
            List<Question> updateList = new ArrayList<>();
            for (Question question : questionList) {
                Integer sort = sortMap.get(question.getId());
                if (ObjectUtil.isNull(sort)) {
                    continue;
                }

                Question updateQuestion = new Question();
                updateQuestion.setId(question.getId());
                updateQuestion.setSort(sort);
                updateList.add(updateQuestion);
            }

            // 批量更新试题信息排序
            if (CollectionUtil.isNotEmpty(updateList)) {
                dao.updateBatchById(updateList);
            }
            return Result.success(toI18nSuccess());
        } catch (InterruptedException e) {
            log.error("试题排序信息失败", e);
            Thread.currentThread().interrupt();
            throw new BaseException(toI18nFail());
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    /**
     * 试题信息-删除
     *
     * @param id ID主键
     * @return 删除结果
     */
    public Result<String> delete(Long id) {
        // 获取校验试题信息
        Question question = dao.getById(id);
        if (ObjectUtil.isNull(question)) {
            return Result.error("试题信息不存在");
        }

        // 被引用校验
        Boolean citeResult = questionCommonBiz.citeCheck(question.getId());
        if (Boolean.TRUE.equals(citeResult)) {
            return Result.error("该试题已被引用，无法被删除");
        }

        // 删除试题选项
        questionOptionDao.deleteByQuestionId(id);

        // 删除试题
        dao.removeById(id);

        log.warn("【删除题目】删除题目信息：{}", JSONUtil.toJsonStr(question));
        return Result.success(toI18nSuccess());
    }

    /**
     * 试题信息-批量删除
     *
     * @param ids 主键ID
     * @return 删除结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<String> deleteBatch(Collection<Long> ids) {
        List<Question> questions = dao.listByIds(ids);
        if (CollectionUtil.isEmpty(questions)) {
            return Result.error("试题不存在");
        }
        Set<Long> questionIds = questions.stream().map(Question::getId).collect(Collectors.toSet());

        Map<Long, Boolean> citeMap = questionCommonBiz.getQuestionCiteStatus(questionIds);

        // 需要删除的题目ID
        Set<Long> deleteQuestionIds = questionIds.stream().filter(item -> !citeMap.getOrDefault(item, Boolean.FALSE)).collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(deleteQuestionIds)) {
            return Result.success(toI18nSuccess());
        }

        // 删除试题选项
        questionOptionDao.deleteByQuestionIds(deleteQuestionIds);

        // 删除试题
        dao.removeByIds(deleteQuestionIds);

        for (Question question : questions) {
            log.warn("【批量删除题目】删除题目信息：{}", JSONUtil.toJsonStr(question));
        }
        return Result.success(toI18nSuccess());
    }

    /**
     * 试题信息-移动
     *
     * @param req 试题信息-移动对象
     * @return 移动结果
     */
    public Result<String> move(AdminQuestionMoveReq req) {
        Category category = categoryDao.getById(req.getCategoryId());
        if (ObjectUtil.isNull(category) || !CategoryTypeEnum.QUESTION.getCode().equals(category.getCategoryType())) {
            return Result.error("试题目录不存在");
        }

        List<Question> questions = dao.listByIds(req.getIds());
        if (CollectionUtil.isEmpty(questions)) {
            return Result.error("试题不存在");
        }
        Set<Long> questionIds = questions.stream().map(Question::getId).collect(Collectors.toSet());

        dao.lambdaUpdate()
                .in(Question::getId, questionIds)
                .set(Question::getCategoryId, req.getCategoryId())
                .update();

        for (Question question : questions) {
            log.warn("【批量移动题目】新分类：{}-题目信息：{}", category.getId(), JSONUtil.toJsonStr(question));
        }
        return Result.success(toI18nSuccess());
    }

    /**
     * 试题信息-分类统计
     *
     * @param req 分类统计对象
     * @return 统计结果
     */
    public Result<List<AdminQuestionTypeCountResp>> typeCount(AdminQuestionTypeCountReq req) {
        // 分类条件
        List<Long> categoryIds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(req.getCategoryIds())) {
            categoryIds.addAll(req.getCategoryIds());
            List<Long> childrenIds = categoryCommonBiz.listChildrenIdByIds(CategoryTypeEnum.QUESTION.getCode(), req.getCategoryIds());
            if (CollectionUtil.isNotEmpty(childrenIds)) {
                categoryIds.addAll(childrenIds);
            }
        }

        LambdaQueryWrapper<Question> wrapper = new QueryWrapper<Question>()
                .select(QuestionDao.QUESTION_TYPE_GROUP_COUNT)
                .lambda()
                .eq(Question::getStatus, StatusEnum.NORMAL.getCode())
                .notIn(CollectionUtil.isNotEmpty(req.getExcludeIds()), Question::getId, req.getExcludeIds())
                .in(CollectionUtil.isNotEmpty(categoryIds), Question::getCategoryId, categoryIds)
                .groupBy(Question::getQuestionType);
        List<QuestionTypeCountResp> countList = dao.selectObjs(wrapper, QuestionTypeCountResp.class);

        Map<Integer, Long> countMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(countList)) {
            countList.forEach(item -> countMap.put(item.getQuestionType(), item.getCount()));
        }

        List<AdminQuestionTypeCountResp> respList = new ArrayList<>();
        for (QuestionTypeEnum typeEnum : QuestionTypeEnum.values()) {
            AdminQuestionTypeCountResp questionTypeCount = new AdminQuestionTypeCountResp();
            questionTypeCount.setQuestionType(typeEnum.getCode());

            Long count = countMap.get(typeEnum.getCode());
            questionTypeCount.setCount(ObjectUtil.isNotNull(count) ? count : 0L);
            respList.add(questionTypeCount);
        }
        return Result.success(respList);
    }

    /**
     * 试题信息-随机选择
     *
     * @param req 随机选择对象
     * @return 抽取题目数
     */
    public Result<List<AdminQuestionRandomSelectionResp>> randomSelection(AdminQuestionRandomSelectionReq req) {
        if (CollectionUtil.isEmpty(req.getTypeCounts())) {
            return Result.error("随机选题数量不能为空");
        }
        long questionCount = req.getTypeCounts().stream()
                .filter(item -> ObjectUtil.isNotNull(item.getCount()))
                .mapToLong(AdminQuestionRandomSelectionReq.TypeCount::getCount)
                .sum();
        if (questionCount < 1) {
            return Result.error("随机选题数量不能为空");
        }

        // 分类条件
        List<Long> categoryIds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(req.getCategoryIds())) {
            categoryIds.addAll(req.getCategoryIds());
            List<Long> childrenIds = categoryCommonBiz.listChildrenIdByIds(CategoryTypeEnum.QUESTION.getCode(), req.getCategoryIds());
            if (CollectionUtil.isNotEmpty(childrenIds)) {
                categoryIds.addAll(childrenIds);
            }
        }

        List<Question> questionList = dao.lambdaQuery()
                .eq(Question::getStatus, StatusEnum.NORMAL.getCode())
                .notIn(CollectionUtil.isNotEmpty(req.getExcludeIds()), Question::getId, req.getExcludeIds())
                .in(CollectionUtil.isNotEmpty(categoryIds), Question::getCategoryId, categoryIds)
                .list();
        if (CollectionUtil.isEmpty(questionList)) {
            return Result.error("暂无可用试题");
        }

        // 抽题
        List<AdminQuestionRandomSelectionResp> resultList = new ArrayList<>();
        for (AdminQuestionRandomSelectionReq.TypeCount rule : req.getTypeCounts()) {
            // 抽题数量为空，跳过
            if (ObjectUtil.isNull(rule.getCount()) || rule.getCount() < 1) {
                continue;
            }

            // 获取目标题目
            List<Question> targetList = questionList.stream()
                    .filter(item -> rule.getQuestionType().equals(item.getQuestionType()))
                    .collect(Collectors.toList());

            // 校验题目数量
            if (CollectionUtil.isEmpty(targetList) || targetList.size() < rule.getCount()) {
                QuestionTypeEnum questionTypeEnum = QuestionTypeEnum.byCode(rule.getQuestionType());
                if (ObjectUtil.isNotNull(questionTypeEnum)) {
                    return Result.error(questionTypeEnum.getDesc() + "题目数量不足");
                } else {
                    return Result.error("题目数量不足");
                }
            }
            // 抽题
            List<Question> selectedList = targetList.subList(0, rule.getCount().intValue());
            resultList.addAll(BeanUtil.copyProperties(selectedList, AdminQuestionRandomSelectionResp.class));
        }


        Set<Long> questionIds = resultList.stream().map(AdminQuestionRandomSelectionResp::getId).collect(Collectors.toSet());
        List<QuestionDetailResp> questionDetailList = questionCommonBiz.listDetailByIds(questionIds);
        Map<Long, QuestionDetailResp> questionDetailMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(questionDetailList)) {
            questionDetailList.forEach(item -> questionDetailMap.put(item.getId(), item));
        }

        // 处理查询出来的数据
        for (AdminQuestionRandomSelectionResp resp : resultList) {
            resp.setOptionCount(0);
            resp.setOptions(Collections.emptyList());
            resp.setQuestionAnswerIds(Collections.emptyList());

            Integer questionType = resp.getQuestionType();

            QuestionDetailResp question = questionDetailMap.get(resp.getId());

            // 定义一个收集正确答案id的集合
            if (QuestionTypeEnum.isExistOption(questionType)) {
                // 获取试题选项
                resp.setOptions(BeanUtil.copyProperties(question.getOptions(), AdminQuestionRandomSelectionResp.Option.class));
                resp.setQuestionAnswerIds(question.getQuestionAnswerIds());
            } else if (QuestionTypeEnum.GAP_FILLING.getCode().equals(questionType)) {
                resp.setOptionCount(question.getOptionCount());
            }
        }
        return Result.success(resultList);
    }

    /**
     * 试题信息-上传Excel文件解析
     *
     * @param file Excel文件
     * @return 解析结果
     */
    public Result<AdminQuestionUploadParseResp> uploadParseExcel(MultipartFile file) {
        if (ObjectUtil.isNull(file)) {
            return Result.error("上传文件不能为空");
        }
        String fileName = file.getOriginalFilename();
        if (fileName == null || StrUtil.isBlank(fileName)) {
            return Result.error("文件名称获取失败");
        }
        if (!(fileName.endsWith(".xls") || fileName.endsWith(".xlsx"))) {
            return Result.error("文件格式错误");
        }

        try {
            AdminQuestionUploadParseResp resp = new AdminQuestionUploadParseResp();
            resp.setFileName(fileName);

            int headRowNumber = 2;
            List<QuestionUploadExcel> readList = EasyExcel.read(file.getInputStream(), QuestionUploadExcel.class, new SyncReadListener()).sheet().headRowNumber(headRowNumber).doReadSync();
            if (CollectionUtil.isEmpty(readList)) {
                resp.setErrorMessages(Collections.singletonList("上传文件内容不能为空"))
                        .setSuccessCount(0)
                        .setErrorCount(0)
                        .setDuplicationInfos(Collections.emptyList());
                return Result.success(resp);
            }

            int successCount = 0;
            int failureCount = 0;
            List<String> errMsgList = new ArrayList<>();

            // 导入校验
            int rowNo = headRowNumber;
            for (QuestionUploadExcel uploadInfo : readList) {
                rowNo++;
                String check = checkUploadQuestion(uploadInfo);
                if (StrUtil.isBlank(check)) {
                    successCount++;
                } else {
                    failureCount++;
                    errMsgList.add("行号" + rowNo + check);
                }
            }

            // 校验重复
            Set<String> questionTitles = readList.stream().map(QuestionUploadExcel::getQuestionTitle).collect(Collectors.toSet());
            List<Question> questionList = dao.lambdaQuery().in(Question::getQuestionTitle, questionTitles).list();
            Map<Integer, Map<String, List<Question>>> questionMap = new HashMap<>();
            Map<Long, Category> categoryMap = new HashMap<>();
            if (CollectionUtil.isNotEmpty(questionList)) {
                questionMap.putAll(questionList.stream().collect(Collectors.groupingBy(Question::getQuestionType, Collectors.groupingBy(Question::getQuestionTitle))));

                Set<Long> categoryIds = questionList.stream().map(Question::getCategoryId).collect(Collectors.toSet());
                List<Category> categoryList = categoryDao.listByIds(categoryIds);
                if (CollectionUtil.isNotEmpty(categoryList)) {
                    categoryList.forEach(item -> categoryMap.put(item.getId(), item));
                }
            }

            List<AdminQuestionUploadParseResp.DuplicationInfo> duplicationInfos = new ArrayList<>();
            int duplicationRowNo = headRowNumber;
            for (QuestionUploadExcel info : readList) {
                duplicationRowNo++;

                QuestionTypeEnum questionTypeEnum = QuestionTypeEnum.byDesc(info.getQuestionType());
                if (ObjectUtil.isNull(questionTypeEnum)) {
                    continue;
                }

                List<AdminQuestionUploadParseResp.Question> questions = new ArrayList<>();
                // 校验数据库是否存在重复
                Map<String, List<Question>> titleQuestionMap = questionMap.get(questionTypeEnum.getCode());
                if (CollectionUtil.isNotEmpty(titleQuestionMap)) {
                    List<Question> duplicationQuestionList = titleQuestionMap.get(info.getQuestionTitle());
                    if (CollectionUtil.isNotEmpty(duplicationQuestionList)) {
                        List<AdminQuestionUploadParseResp.Question> respQuestionList = BeanUtil.copyProperties(duplicationQuestionList, AdminQuestionUploadParseResp.Question.class);
                        for (AdminQuestionUploadParseResp.Question question : respQuestionList) {
                            Category category = categoryMap.get(question.getCategoryId());
                            question.setCategoryName(ObjectUtil.isNotNull(category) ? category.getCategoryName() : "");
                            question.setExist(Boolean.TRUE);
                        }
                        questions.addAll(respQuestionList);
                    }
                }

                // 校验文件内是否重复
                int fileRowNo = headRowNumber;
                for (QuestionUploadExcel questionInfo : readList) {
                    fileRowNo++;

                    if (!info.getQuestionType().equals(questionInfo.getQuestionType())) {
                        continue;
                    }
                    if (!info.getQuestionTitle().equals(questionInfo.getQuestionTitle())) {
                        continue;
                    }
                    if (duplicationRowNo == fileRowNo) {
                        continue;
                    }

                    DifficultyLevelEnum difficultyLevelEnum = DifficultyLevelEnum.byDesc(questionInfo.getDifficultyLevel());

                    AdminQuestionUploadParseResp.Question question = new AdminQuestionUploadParseResp.Question()
                            .setExist(Boolean.FALSE)
                            .setQuestionType(questionTypeEnum.getCode())
                            .setDifficultyLevel(ObjectUtil.isNotNull(difficultyLevelEnum) ? difficultyLevelEnum.getCode() : null)
                            .setQuestionTitle(questionInfo.getQuestionTitle())
                            .setRowNo(fileRowNo);
                    questions.add(question);
                }

                if (CollectionUtil.isNotEmpty(questions)) {
                    AdminQuestionUploadParseResp.DuplicationInfo duplicationInfo = new AdminQuestionUploadParseResp.DuplicationInfo()
                            .setRowNo(duplicationRowNo)
                            .setQuestionType(questionTypeEnum.getCode())
                            .setQuestionTitle(info.getQuestionTitle())
                            .setDuplicationCount(questions.size())
                            .setQuestions(questions);
                    duplicationInfos.add(duplicationInfo);
                }
            }

            // 缓存解析结果
            if (successCount > 0 && failureCount <= 0) {
                int timeout = 2 * 60 * 60;
                String importToken = cacheParseInfo(readList, timeout);
                resp.setUploadToken(importToken);
                resp.setTimeout(timeout);
            }

            // 处理返回结果
            resp.setSuccessCount(successCount);
            resp.setErrorCount(failureCount);
            resp.setErrorMessages(errMsgList);
            resp.setDuplicationInfos(duplicationInfos);
            return Result.success(resp);
        } catch (IOException e) {
            log.error("解析导入文件异常", e);
            return Result.error("上传文件解析失败");
        }
    }

    /**
     * 校验导入试题
     *
     * @param uploadInfo 导入参数
     * @return 错误信息
     */
    private String checkUploadQuestion(QuestionUploadExcel uploadInfo) {
        StringBuilder sb = new StringBuilder();
        if (StrUtil.isBlank(uploadInfo.getQuestionType())) {
            sb.append("试题类型不存在");
        }
        QuestionTypeEnum questionTypeEnum = QuestionTypeEnum.byDesc(uploadInfo.getQuestionType());
        if (ObjectUtil.isNull(questionTypeEnum)) {
            sb.append("试题类型不存在");
        }
        if (StrUtil.isBlank(uploadInfo.getQuestionTitle())) {
            sb.append("题目内容不存在");
        }
        if (StrUtil.isBlank(uploadInfo.getAnswer())) {
            sb.append("题目答案不存在");
            return sb.toString();
        }
        if (ObjectUtil.isNotNull(questionTypeEnum)) {
            // 选择题判断选项内容、和答案范围是否选项范围内
            if (QuestionTypeEnum.SINGLE_CHOICE.equals(questionTypeEnum) || QuestionTypeEnum.MULTIPLE_CHOICE.equals(questionTypeEnum)) {
                sb.append(checkOption(uploadInfo, questionTypeEnum));
            } else if (QuestionTypeEnum.JUDGMENT.equals(questionTypeEnum)) {
                if (!BaseConstant.ESTIMATE_ANSWER_LIST.contains(uploadInfo.getAnswer())) {
                    sb.append("判断题答案").append(uploadInfo.getAnswer()).append("不是有效答案");
                }
            }
        }
        // 难度等级
        if (StrUtil.isBlank(uploadInfo.getDifficultyLevel())) {
            sb.append("题目难易程度不能为空");
        }
        DifficultyLevelEnum difficultyLevelEnum = DifficultyLevelEnum.byDesc(uploadInfo.getDifficultyLevel());
        if (ObjectUtil.isNull(difficultyLevelEnum)) {
            sb.append("题目难易程度不存在");
        }
        return sb.toString();
    }

    /**
     * 校验选择题选项和答案
     *
     * @param uploadInfo       题目信息
     * @param questionTypeEnum 题目类型
     * @return 错误信息
     */
    private String checkOption(QuestionUploadExcel uploadInfo, QuestionTypeEnum questionTypeEnum) {
        StringBuilder sb = new StringBuilder();
        List<String> optionList = new ArrayList<>();

        if (StrUtil.isBlank(uploadInfo.getOptionA())) {
            sb.append("题目选项A不能为空");
        } else {
            optionList.add("A");
        }
        if (StrUtil.isBlank(uploadInfo.getOptionB())) {
            sb.append("题目选项B不能为空");
        } else {
            optionList.add("B");
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionC())) {
            optionList.add("C");
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionD())) {
            if (StrUtil.isBlank(uploadInfo.getOptionC())) {
                sb.append("题目选项C不能为空");
            } else {
                optionList.add("D");
            }
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionE())) {
            if (StrUtil.isBlank(uploadInfo.getOptionD())) {
                sb.append("题目选项D不能为空");
            } else {
                optionList.add("E");
            }
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionF())) {
            if (StrUtil.isBlank(uploadInfo.getOptionE())) {
                sb.append("题目选项E不能为空");
            } else {
                optionList.add("F");
            }
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionG())) {
            if (StrUtil.isBlank(uploadInfo.getOptionF())) {
                sb.append("题目选项F不能为空");
            } else {
                optionList.add("G");
            }
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionH())) {
            if (ObjectUtil.isNotNull(StrUtil.isBlank(uploadInfo.getOptionG()))) {
                sb.append("题目选项G不能为空");
            } else {
                optionList.add("H");
            }
        }

        if (QuestionTypeEnum.SINGLE_CHOICE.equals(questionTypeEnum)) {
            if (!optionList.contains(uploadInfo.getAnswer())) {
                sb.append("题目答案").append(uploadInfo.getAnswer()).append("不是有效选项");
            }
        } else {
            for (int i = 0; i < uploadInfo.getAnswer().length(); i++) {
                if (!optionList.contains(String.valueOf(uploadInfo.getAnswer().charAt(i)))) {
                    sb.append("题目答案").append(uploadInfo.getAnswer().charAt(i)).append("不是有效选项");
                }
            }
        }
        return sb.toString();
    }

    /**
     * 将导入试题存入缓存
     *
     * @param readList 读取文件信息
     * @return 错误信息
     */
    private String cacheParseInfo(List<QuestionUploadExcel> readList, int timeout) {
        // 定义一个收集缓存试题的集合
        List<QuestionUploadExcelParse> cacheList = new ArrayList<>();

        for (QuestionUploadExcel uploadInfo : readList) {
            QuestionUploadExcelParse questionCache = new QuestionUploadExcelParse();
            questionCache.setQuestionType(QuestionTypeEnum.byDesc(uploadInfo.getQuestionType()).getCode());
            questionCache.setDifficultyLevel(DifficultyLevelEnum.byDesc(uploadInfo.getDifficultyLevel()).getCode());
            questionCache.setQuestionTitle(uploadInfo.getQuestionTitle());
            questionCache.setQuestionAnalysis(uploadInfo.getQuestionAnalysis());

            // 判断题，填空题，问答题直接设置正确答案
            if (QuestionTypeEnum.JUDGMENT.getCode().equals(questionCache.getQuestionType()) || QuestionTypeEnum.GAP_FILLING.getCode().equals(questionCache.getQuestionType()) || QuestionTypeEnum.SHORT_ANSWER.getCode().equals(questionCache.getQuestionType())) {
                questionCache.setCorrectAnswer(uploadInfo.getAnswer());
            } else {
                // 单选题，多选题转换选项，拼接答案
                questionCache.setOptions(getOptionList(uploadInfo));
                questionCache.setCorrectAnswer(getAnswer(uploadInfo, questionCache));
            }

            cacheList.add(questionCache);
        }
        String importToken = IdUtil.simpleUUID();

        // 放入缓存
        cacheRedis.set(RedisConstant.Exam.QUESTION_IMPORT + importToken, JSONUtil.toJsonStr(cacheList), timeout, TimeUnit.SECONDS);
        return importToken;
    }

    /**
     * 获取选择题选项集合
     *
     * @param uploadInfo 题目对象
     * @return 选项集合
     */
    private List<QuestionUploadExcelParse.Option> getOptionList(QuestionUploadExcel uploadInfo) {
        List<QuestionUploadExcelParse.Option> options = new ArrayList<>();

        // 存储答案选项列表
        if (StrUtil.isNotBlank(uploadInfo.getOptionA())) {
            options.add(new QuestionUploadExcelParse.Option().setOptionContent(uploadInfo.getOptionA()));
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionB())) {
            options.add(new QuestionUploadExcelParse.Option().setOptionContent(uploadInfo.getOptionB()));
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionC())) {
            options.add(new QuestionUploadExcelParse.Option().setOptionContent(uploadInfo.getOptionC()));
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionD())) {
            options.add(new QuestionUploadExcelParse.Option().setOptionContent(uploadInfo.getOptionD()));
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionE())) {
            options.add(new QuestionUploadExcelParse.Option().setOptionContent(uploadInfo.getOptionE()));
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionF())) {
            options.add(new QuestionUploadExcelParse.Option().setOptionContent(uploadInfo.getOptionF()));
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionG())) {
            options.add(new QuestionUploadExcelParse.Option().setOptionContent(uploadInfo.getOptionG()));
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionH())) {
            options.add(new QuestionUploadExcelParse.Option().setOptionContent(uploadInfo.getOptionH()));
        }

        if (CollectionUtil.isNotEmpty(options)) {
            int sort = 0;
            for (QuestionUploadExcelParse.Option option : options) {
                option.setSort(++sort);
            }
        }
        return options;
    }

    /**
     * 返回单选题或多选题正确答案
     *
     * @param uploadInfo 题目对象
     * @param parseCache 缓存试题
     * @return 试题答案
     */
    private String getAnswer(QuestionUploadExcel uploadInfo, QuestionUploadExcelParse parseCache) {
        String answer;

        // 定义一个收集答案的map
        Map<String, String> map = new HashMap<>();
        if (StrUtil.isNotBlank(uploadInfo.getOptionA())) {
            map.put("A", uploadInfo.getOptionA());
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionB())) {
            map.put("B", uploadInfo.getOptionB());
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionC())) {
            map.put("C", uploadInfo.getOptionC());
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionD())) {
            map.put("D", uploadInfo.getOptionD());
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionE())) {
            map.put("E", uploadInfo.getOptionE());
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionF())) {
            map.put("F", uploadInfo.getOptionF());
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionG())) {
            map.put("G", uploadInfo.getOptionG());
        }
        if (StrUtil.isNotBlank(uploadInfo.getOptionH())) {
            map.put("H", uploadInfo.getOptionH());
        }
        if (QuestionTypeEnum.SINGLE_CHOICE.getCode().equals(parseCache.getQuestionType())) {
            answer = map.get(uploadInfo.getAnswer());
        } else {
            // 解析多选题的正确答案
            List<String> answerList = new ArrayList<>();
            for (int i = 0; i < uploadInfo.getAnswer().length(); i++) {
                answerList.add(map.get(String.valueOf(uploadInfo.getAnswer().charAt(i))));
            }
            answer = String.join(BaseConstant.SAVE_SEPARATOR, answerList);
        }
        return answer;
    }

    @Transactional(rollbackFor = Exception.class)
    public Result<String> importQuestion(AdminQuestionUploadExcelReq req) {
        Category category = categoryDao.getById(req.getCategoryId());
        if (ObjectUtil.isNull(category)) {
            return Result.error("分类信息不存在");
        }

        String redisValue = cacheRedis.get(RedisConstant.Exam.QUESTION_IMPORT + req.getUploadToken());
        if (StrUtil.isBlank(redisValue)) {
            return Result.error("获取导入试题信息失败");
        }
        List<QuestionUploadExcelParse> parseInfoList = JSONUtil.toList(redisValue, QuestionUploadExcelParse.class);

        if (CollectionUtil.isEmpty(parseInfoList)) {
            return Result.error("获取导入试题信息为空");
        }

        // 获取试题最大排序
        int maxSort = dao.getMaxSort();
        List<Question> questionList = new ArrayList<>();
        List<QuestionOption> optionList = new ArrayList<>();
        int index = 1;
        for (QuestionUploadExcelParse parseInfo : parseInfoList) {
            Question question = BeanUtil.copyProperties(parseInfo, Question.class);
            question.setId(IdWorker.getId());
            question.setCategoryId(category.getId());
            question.setQuestionAnswer(parseInfo.getCorrectAnswer());
            question.setQuestionAnalysis(StrUtil.isNotBlank(parseInfo.getQuestionAnalysis()) ? parseInfo.getQuestionAnalysis() : "");
            question.setSort(maxSort + index++);
            questionList.add(question);
            if (QuestionTypeEnum.SINGLE_CHOICE.getCode().equals(question.getQuestionType()) || QuestionTypeEnum.MULTIPLE_CHOICE.getCode().equals(question.getQuestionType())) {
                // 遍历设置试题选项
                List<QuestionOption> questionOptionList = new ArrayList<>();
                for (QuestionUploadExcelParse.Option optionContent : parseInfo.getOptions()) {
                    QuestionOption option = new QuestionOption();
                    option.setId(IdWorker.getId());
                    option.setQuestionId(question.getId());
                    option.setOptionContent(optionContent.getOptionContent());
                    option.setSort(optionContent.getSort());
                    questionOptionList.add(option);
                }

                optionList.addAll(questionOptionList);
            } else if (QuestionTypeEnum.JUDGMENT.getCode().equals(question.getQuestionType())) {
                QuestionOption right = new QuestionOption();
                right.setId(IdWorker.getId());
                right.setQuestionId(question.getId());
                right.setOptionContent("对");
                right.setSort(0);
                optionList.add(right);

                QuestionOption wrong = new QuestionOption();
                wrong.setId(IdWorker.getId());
                wrong.setQuestionId(question.getId());
                wrong.setOptionContent("错");
                wrong.setSort(1);
                optionList.add(wrong);
            }
        }
        // 批量保存
        dao.saveBatch(questionList);
        if (CollectionUtil.isNotEmpty(optionList)) {
            questionOptionDao.saveBatch(optionList);
        }

        if (CollectionUtil.isNotEmpty(questionList)) {
            for (Question saveQuestion : questionList) {
                log.warn("【批量导入试题】题目内容：{}", JSONUtil.toJsonStr(saveQuestion));
            }
        }
        return Result.success(toI18nSuccess());
    }

    /**
     * 试题信息-引用列表
     *
     * @param id 试题ID
     * @return 引用信息
     */
    public Result<List<AdminQuestionCiteListResp>> citeList(Long id) {
        List<AdminQuestionCiteListResp> respList = new ArrayList<>();

        // 查看是否被试卷引用
        List<PaperQuestion> paperQuestionList = paperQuestionDao.lambdaQuery()
                .eq(PaperQuestion::getQuestionId, id)
                .list();
        if (CollectionUtil.isNotEmpty(paperQuestionList)) {
            Set<Long> paperIds = paperQuestionList.stream().map(PaperQuestion::getPaperId).collect(Collectors.toSet());
            List<Paper> paperList = paperDao.lambdaQuery()
                    .in(Paper::getId, paperIds)
                    .orderByDesc(Paper::getSort).orderByDesc(Paper::getId)
                    .list();
            if (CollectionUtil.isNotEmpty(paperList)) {
                paperList.forEach(item -> respList.add(new AdminQuestionCiteListResp(CiteResourceTypeEnum.PAPER.getCode(), item.getId(), item.getPaperName())));
            }
        }


        return Result.success(respList);
    }

    public Result<String> create(AiQuestion req) {
        String aiToken = IdUtil.simpleUUID();
        cacheRedis.set(RedisConstant.Exam.QUESTION_AI + aiToken, req, 2 * 60 * 60, TimeUnit.SECONDS);
        return Result.success(aiToken);
    }

    public ResponseBodyEmitter completions(String aiToken) {
        // 出题规则
        AiQuestion aiQuestion = cacheRedis.get(RedisConstant.Exam.QUESTION_AI + aiToken, AiQuestion.class);
        if (ObjectUtil.isNull(aiQuestion)) {
            throw new BaseException("系统繁忙，请稍后再试");
        }

        // 禁用缓存
        response.setHeader("Cache-Control", "no-cache");

        // 调用大模型接口
        Llm llm = sysConfigCommonBiz.getSysConfig(Llm.class);
        return llmService.questionAiCompletions(llm, aiQuestion);
    }
}
